package com.woniuxy.project115.kaer.mall.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.json.JSONUtil;
import cn.hutool.system.UserInfo;
//import com.alipay.api.AlipayClient;
//import com.alipay.api.domain.Product;
//import com.alipay.api.internal.util.AlipaySignature;
//import com.alipay.api.request.AlipayTradePagePayRequest;
//import com.alipay.api.request.AlipayTradeQueryRequest;
//import com.alipay.api.response.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.project115.kaer.commons.util.Result;
import com.woniuxy.project115.kaer.mall.config.WebSocketServer;
import com.woniuxy.project115.kaer.mall.entity.OrderLog;
import com.woniuxy.project115.kaer.mall.entity.OrderOfProduct;
import com.woniuxy.project115.kaer.mall.entity.ProductInfo;
import com.woniuxy.project115.kaer.mall.entity.ProductOrderInfo;
import com.woniuxy.project115.kaer.mall.mapper.OrderLogMapper;
import com.woniuxy.project115.kaer.mall.mapper.OrderOfProductMapper;
import com.woniuxy.project115.kaer.mall.mapper.ProductInfoMapper;
import com.woniuxy.project115.kaer.mall.mapper.ProductOrderInfoMapper;
import com.woniuxy.project115.kaer.mall.param.OrderParam;
import com.woniuxy.project115.kaer.mall.service.ProductOrderInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import com.woniuxy.project115.kaer.user.feign.UserFeignClient;
import com.woniuxy.project115.kaer.user.form.ScoreChangeForm;

/**
 * <p>
 * 订单详情表 服务实现类
 * </p>
 *
 * @author lyc
 * @since 2025年02月17日
 */
@Service
@Transactional
public class ProductOrderInfoServiceImpl extends ServiceImpl<ProductOrderInfoMapper, ProductOrderInfo> implements ProductOrderInfoService {
    @Resource
    private ProductOrderInfoMapper productOrderInfoMapper;
    @Resource
    private ProductInfoMapper productInfoMapper;
//    @Resource
//    private AlipayClient alipayClient;
    //注入支付宝公钥用于验证签名
    @Value("${alipay.config.alipayPublicKey}")
    private String alipayPublicKey;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private OrderOfProductMapper orderOfProductMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private UserFeignClient userFeignClient;
    @Value("${alipay.notifyUrl}")
    private String notifyUrl;
    @Resource
    private OrderLogMapper orderLogMapper;


    @Override
    public String pay(String orderNum, Integer userId) throws Exception {
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectOne(new QueryWrapper<ProductOrderInfo>().eq("order_num", orderNum).eq("user_id", userId));
        if (orderInfo == null) {
            throw new Exception("订单不存在");
        }
        if (!orderInfo.getPayState().equals("未支付")||!orderInfo.getOrderState().equals("待付款")) {
            throw new Exception("订单状态异常");
        }
//        //调用支付宝支付接口
//        // 实例化网页支付请求对象
//        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
//        HashMap<String, Object> param = new HashMap<>();
//        param.put("out_trade_no", orderInfo.getOrderNum());
        //获取用户积分
        Result<Integer> result = userFeignClient.getUserInfo(userId);
        BigDecimal score = new BigDecimal(result.getData());
        //积分折算
        BigDecimal totalPrice = orderInfo.getTotalPrice();
        // 计算实际需要支付的金额
        BigDecimal actualAmount;
        if (score.compareTo(totalPrice) >= 0) {
            // 如果积分大于等于总价，实际支付金额为 25(运费)
            actualAmount=new BigDecimal(25);
        } else if (score.compareTo(BigDecimal.ZERO)<=0) {
            // 当积分小于等于 0 时，实际支付金额为总价
            actualAmount=totalPrice;
        }else {
            // 当积分大于 0 且小于总价时，实际支付金额为总价减去积分
        actualAmount = totalPrice.subtract(score);
        }
        //记录支付时间
        orderInfo.setPayTime(LocalDateTime.now());
        orderInfo.setRealPay(actualAmount);
        productOrderInfoMapper.updateById(orderInfo);
        //记录日志
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNum(orderInfo.getOrderNum());
        orderLog.setOperateType("用户支付订单("+actualAmount+")");
        orderLog.setOperateTime(LocalDateTime.now());
        orderLog.setUserId(orderInfo.getUserId());
        orderLogMapper.insert(orderLog);
//        param.put("total_amount", actualAmount.doubleValue());
//        param.put("subject", "卡尔商城订单");
//        param.put("body", "商城订单支付");
//        param.put("product_code", "FAST_INSTANT_TRADE_PAY");
//        LocalDateTime expire = orderInfo.getCreateTime().plusMinutes(15);
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//        param.put("time_expire", expire.format(formatter));
//        //将键值对参数转为JSON格式
//        String content = JSONUtil.toJsonStr(param);
//        //设置同步回调(用户支付成功后跳转的页面)
//        request.setReturnUrl("http://www.woniuxy.com");
//        //设置异步回调(支付宝服务器向该地址发送支付结果)
//        request.setNotifyUrl(notifyUrl);
//        request.setBizContent(content);
//        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
//        if (response.isSuccess()) {
//            //返回支付宝响应的支付表单html内容
//            return response.getBody();
//        }
//        throw new Exception("支付失败");
        Map<String, String> params = new HashMap<>();
        params.put("out_trade_no",orderNum);
        params.put("total_amount",actualAmount.toString());
        params.put("trade_status","TRADE_SUCCESS");
        handleOrder(params);
        return null;
    }

    @Override
    public ProductOrderInfo order(OrderParam param) throws Exception {
        //先排序，防止死锁
        List<Integer> productIdList = param.getProductIdList();
        Collections.sort(productIdList);
        //判断购物车中是否存在商品信息
        //查询出的购物车信息保存在键值对中用于失败时补偿
        ArrayList<Map<Object, Object>> carInfo = new ArrayList<>();
        for (Integer productId : param.getProductIdList()) {
            if (stringRedisTemplate.opsForZSet().score("cart:list:" + param.getUserId(), productId.toString()) == null) {
                throw new Exception("购物车中不存在该商品");
            }
            //判断库存是否充足
            Integer number = Integer.parseInt(stringRedisTemplate.opsForHash().get("cart:info:" + param.getUserId() + ":" + productId, "number").toString());
            ProductInfo productInfo = productInfoMapper.selectById(productId);
            if (productInfo.getNumber() < number) {
                throw new Exception("库存不足");
            }
            //判断商品是否下架(0下架，1上架,2删除)
            if (productInfo.getProductState() != 1) {
                throw new Exception("商品已下架");
            }
            //获取购物车的排序值保存到键值对中便于补偿
            Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("cart:info:" + param.getUserId() + ":" + productId);
            entries.put("score", stringRedisTemplate.opsForZSet().score("cart:list:" + param.getUserId(), productId.toString()));
            carInfo.add(entries);
        }
        //创建单锁
        RLock[] rLocks = new RLock[productIdList.size()];
        for (int i = 0; i < productIdList.size(); i++) {
            //创建公平锁
            rLocks[i] = redissonClient.getLock("lock:productId:" + productIdList.get(i));
        }
        //创建联锁
        RLock multiLock = redissonClient.getMultiLock(rLocks);
        try {
            //加锁
            multiLock.lock();
            //创建订单号
            Snowflake snowflake = new Snowflake(1, 1);
            String orderNum = snowflake.nextIdStr();
            //创建订单
            ProductOrderInfo orderInfo = new ProductOrderInfo();
            orderInfo.setOrderNum(orderNum);
            orderInfo.setUserId(param.getUserId());
            orderInfo.setCreateTime(LocalDateTime.now());
            orderInfo.setAddressInfo(param.getAddressInfo());
            orderInfo.setReceiverName(param.getReceiverName());
            orderInfo.setPhone(param.getReceiverPhone());
            orderInfo.setRemarks(param.getRemarks());
            orderInfo.setOrderState("待付款");
            try {
                //计算订单总价
                for (Map<Object, Object> carInfoOfProduct : carInfo) {
                    Integer productId = Integer.parseInt(carInfoOfProduct.get("productId").toString());
                    Integer number = Integer.parseInt(carInfoOfProduct.get("number").toString());
                    OrderOfProduct orderOfProduct = new OrderOfProduct();
                    orderOfProduct.setOrderNum(orderNum);
                    orderOfProduct.setProductId(productId);
                    orderOfProduct.setProductCount(number);
                    ProductInfo productInfo = productInfoMapper.selectById(productId);
                    orderOfProduct.setProductPrice(productInfo.getProductPrice());
                    orderOfProduct.setProductImage(productInfo.getProductImage());
                    orderOfProduct.setProductName(productInfo.getProductName());
                    orderOfProductMapper.insert(orderOfProduct);
                }
                List<OrderOfProduct> orderOfProductList = orderOfProductMapper.selectList(new QueryWrapper<OrderOfProduct>().eq("order_num", orderNum));
                BigDecimal bigDecimal = new BigDecimal(0);
                for (OrderOfProduct orderOfProduct : orderOfProductList) {
                    BigDecimal currentProductPrice = orderOfProduct.getProductPrice().multiply(BigDecimal.valueOf(orderOfProduct.getProductCount()));
                    bigDecimal = bigDecimal.add(currentProductPrice);
                    //更新商品的库存信息
                    ProductInfo productInfo = productInfoMapper.selectById(orderOfProduct.getProductId());
                    productInfo.setNumber(productInfo.getNumber() - orderOfProduct.getProductCount());
                    productInfo.setFreeze(productInfo.getFreeze() + orderOfProduct.getProductCount());
                    productInfoMapper.updateById(productInfo);
                    //删除购物车信息
                    stringRedisTemplate.opsForZSet().remove("cart:list:" + param.getUserId(), productInfo.getProductId()+"");
                    stringRedisTemplate.delete("cart:info:" + param.getUserId()+":"+productInfo.getProductId());
                }
                orderInfo.setTotalPrice(bigDecimal);
                orderInfo.setPayState("未支付");
                productOrderInfoMapper.insert(orderInfo);
                //生成日志
                OrderLog orderLog = new OrderLog();
                orderLog.setOrderNum(orderNum);
                orderLog.setUserId(param.getUserId());
                orderLog.setOperateTime(LocalDateTime.now());
                orderLog.setOperateType("用户下单");
                orderLogMapper.insert(orderLog);
            } catch (Exception e) {
                //如果出现异常则进行补偿
                for (Map<Object, Object> map : carInfo) {
                    Integer number = Integer.valueOf(map.get("number").toString());
                    Integer productId = Integer.valueOf(map.get("productId").toString());
                    //清空购物车和购物车详情
                    stringRedisTemplate.opsForZSet().remove("cart:list:" + param.getUserId(), productId + "");
                    stringRedisTemplate.delete("cart:info:" + param.getUserId()+":"+productId);
                    //补偿购物车和购物车详情
                    BigDecimal scoreBigDecimal = new BigDecimal(map.get("score").toString());
                    long score = scoreBigDecimal.longValue();
                    stringRedisTemplate.opsForZSet().add("cart:list:" + param.getUserId(), productId + "", score);
                    //移除score,不属于购物车详情
                    map.remove("score");
                    stringRedisTemplate.opsForHash().putAll("cart:info:" + param.getUserId()+":"+productId, map);
                }
                throw e;
            }
//将订单编号加入到延迟队列 用于在一段时间之后检查订单的支付状态
            rabbitTemplate.convertAndSend("", "waiting_check_order_queue", orderNum, new CorrelationData(UUID.randomUUID().toString()));
            return orderInfo;
        } finally {
            multiLock.unlock();
        }
    }

    @Override
    public void updateOrder(String orderNum, String payTime) {
        //1.查询订单信息
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectById(orderNum);
        if (orderInfo != null) {
            if (orderInfo.getPayState().equals("未支付")) {
//                payTime=orderInfo.getPayTime().toString();
                orderInfo.setPayState("已支付");
                orderInfo.setOrderState("待发货");
//                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//                System.out.println(payTime);
//                LocalDateTime date = LocalDateTime.parse(payTime, formatter);
//                orderInfo.setPayTime(date);
                productOrderInfoMapper.updateById(orderInfo);
                //查询订单详情
                QueryWrapper<OrderOfProduct> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("order_num", orderNum);
                List<OrderOfProduct> orderOfProductList = orderOfProductMapper.selectList(queryWrapper);
                for (OrderOfProduct orderOfProduct : orderOfProductList) {
                    //使用分布式锁加锁
                    RLock fairLock = redissonClient.getFairLock("lock:productId:" + orderOfProduct.getProductId());
                    try {
                        fairLock.lock();
                        ProductInfo productInfo = productInfoMapper.selectById(orderOfProduct.getProductId());
                        productInfo.setFreeze(productInfo.getFreeze() - orderOfProduct.getProductCount());
                        productInfoMapper.updateById(productInfo);
                    } finally {
                        fairLock.unlock();
                    }
                }
            }
        }
    }

    @Override
    public void cancelOrder(String orderNum,Integer operateId) throws Exception {
        System.out.println(orderNum);
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectOne(new QueryWrapper<ProductOrderInfo>()
                .eq("order_num",orderNum)
                .eq("pay_state","未支付"));
        if (orderInfo != null) {
                orderInfo.setOrderState("已取消");
                productOrderInfoMapper.updateById(orderInfo);
                //查询订单详情
                QueryWrapper<OrderOfProduct> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("order_num", orderNum);
                List<OrderOfProduct> orderOfProductList = orderOfProductMapper.selectList(queryWrapper);
                for (OrderOfProduct orderOfProduct : orderOfProductList) {
                    //使用分布式锁加锁
                    RLock fairLock = redissonClient.getFairLock("lock:productId:" + orderOfProduct.getProductId());
                    try {
                        fairLock.lock();
                        ProductInfo productInfo = productInfoMapper.selectById(orderOfProduct.getProductId());
                        productInfo.setFreeze(productInfo.getFreeze() - orderOfProduct.getProductCount());
                        productInfo.setNumber(productInfo.getNumber() + orderOfProduct.getProductCount());
                        productInfoMapper.updateById(productInfo);
                        //记录日志
                        OrderLog orderLog = new OrderLog();
                        orderLog.setOrderNum(orderNum);
                        if (operateId==1){
                            orderLog.setOperateType("用户取消订单");
                            orderLog.setUserId(orderInfo.getUserId());
                        }else {
                            orderLog.setOperateType("订单超时自动取消");
                            orderLog.setUserId(1);
                        }
                        orderLog.setOperateTime(LocalDateTime.now());
                        orderLog.setOperateTime(LocalDateTime.now());
                        orderLogMapper.insert(orderLog);
                    } finally {
                        fairLock.unlock();
                    }
                }
        }else throw new Exception("订单状态异常");
    }

    @Override
    @Transactional
    public void handleOrder(Map<String, String> params) throws Exception {
        // 验证签名
//        boolean b = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "utf-8", "RSA2");
//        if (b) {
            // 验签成功
            // 处理订单
            String orderNum = params.get("out_trade_no");
            String trade_status = params.get("trade_status");
            String total_amount = params.get("total_amount");
            if ("TRADE_SUCCESS".equals(trade_status)) {
                // 支付成功
                ProductOrderInfo orderInfo = productOrderInfoMapper.selectById(orderNum);
                //获取支付时间
//                String payTime = params.get("gmt_payment");
                String payTime=orderInfo.getPayTime().toString();
                // 更新订单状态
                updateOrder(orderNum, payTime);
                //减少用户积分
                BigDecimal totalPrice = orderInfo.getTotalPrice();
                BigDecimal realPay = new BigDecimal(total_amount);
                int score = totalPrice.subtract(realPay).intValue();
                ScoreChangeForm scoreChangeForm = new ScoreChangeForm();
                scoreChangeForm.setUserId(orderInfo.getUserId());
                scoreChangeForm.setScore(score);
                scoreChangeForm.setType("减");
                userFeignClient.scoreChange(scoreChangeForm);
                // 通知平台账户有新订单，假设平台账户的 userId 是 "platform"
                try {
                    String message = "订单 " + orderNum + " 已支付，请及时处理发货。";
                    WebSocketServer.sendInfo(message, "1");
                } catch (IOException e) {
                    log.error("发送 WebSocket 消息失败: ", e);
                }
            }else{
                throw new Exception("支付失败");
            }
//        }
    }

    @Override
    public void updateRemarks(String orderNum, String remarks) {
        //判断订单是否存在
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectById(orderNum);
        if (orderInfo == null) {
            throw new RuntimeException("订单不存在");
        }
        //判断订单是否已支付
        if (orderInfo.getPayState().equals("已支付")) {
            throw new RuntimeException("订单已支付，无法修改备注");
        }
        //修改订单备注
        orderInfo.setRemarks(remarks);
        productOrderInfoMapper.updateById(orderInfo);
        //记录日志
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNum(orderNum);
        orderLog.setOperateType("用户修改订单备注");
        orderLog.setOperateTime(LocalDateTime.now());
        orderLog.setUserId(orderInfo.getUserId());
        orderLogMapper.insert(orderLog);
    }

    @Override
    public List<ProductOrderInfo> getMyUnpaidOrder(Integer userId) {
        //查询待付款订单信息
        return productOrderInfoMapper.selectList(new QueryWrapper<ProductOrderInfo>().eq("user_id", userId).eq("pay_state", "未支付").eq("order_state", "待付款"));
    }

    @Override
    public List<ProductOrderInfo> getMyUnshippedOrder(Integer userId) {
        return productOrderInfoMapper.selectList(new QueryWrapper<ProductOrderInfo>().eq("user_id", userId).eq("pay_state", "已支付").eq("order_state", "待发货"));
    }

    @Override
    public List<ProductOrderInfo> getMyUnreceivedOrder(Integer userId) {
        return productOrderInfoMapper.selectList(new QueryWrapper<ProductOrderInfo>().eq("user_id", userId).eq("pay_state", "已支付").eq("order_state", "待收货"));
    }

    @Override
    public List<ProductOrderInfo> getMyUncommentOrder(Integer userId) {
        return productOrderInfoMapper.selectList(new QueryWrapper<ProductOrderInfo>().eq("user_id", userId).eq("pay_state", "已支付").eq("order_state", "待评价"));
    }

    @Override
    public List<ProductOrderInfo> getMyCompletedOrder(Integer userId) {
        return productOrderInfoMapper.selectList(new QueryWrapper<ProductOrderInfo>().eq("user_id", userId).eq("pay_state", "已支付").eq("order_state", "已完成"));
    }

    @Override
    public void urge(String orderNum, Integer userId) {
        //判断订单是否存在
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectById(orderNum);
        if (orderInfo == null) {
            throw new RuntimeException("订单不存在");
        }
        //判断订单是否已支付和待发货
        if (orderInfo.getPayState().equals("已支付") && orderInfo.getOrderState().equals("待发货")) {
            try {
                String message = "你好!我的订单 " + orderNum + " 已付款，请及时处理发货!";
                WebSocketServer.sendInfo(message, "1");
            } catch (IOException e) {
                log.error("发送 WebSocket 消息失败: ", e);
            }
        }
    }

    @Override
    public void confirm(String orderNum, Integer userId) throws Exception{
        //判断订单是否存在
        ProductOrderInfo orderInfo = productOrderInfoMapper.selectOne(new QueryWrapper<ProductOrderInfo>().eq("order_num", orderNum).eq("user_id", userId));
        if (orderInfo == null) {
            throw new RuntimeException("订单不存在");
        }
        //判断订单是否已支付和待收货
        if (orderInfo.getPayState().equals("已支付") && orderInfo.getOrderState().equals("待收货")) {
            orderInfo.setOrderState("待评价");
            productOrderInfoMapper.updateById(orderInfo);
            //返还用户积分
//            AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();
//            alipayRequest.setBizContent("{\"out_trade_no\":\""+ orderNum+"\"}");
//            String result = alipayClient.execute(alipayRequest).getBody();
//            System.out.println(result);

//            String payMoney= JSONUtil.parseObj(result).getJSONObject("alipay_trade_query_response").get("total_amount").toString();
            String payMoney=orderInfo.getRealPay().toString();
            //返还用户10%的积分
            int score = (int) (((int) Double.parseDouble(payMoney))*0.1);
            ScoreChangeForm scoreChangeForm = new ScoreChangeForm();
            scoreChangeForm.setUserId(userId);
            scoreChangeForm.setScore(score);
            scoreChangeForm.setType("加");
            userFeignClient.scoreChange(scoreChangeForm);
            //记录日志
            OrderLog orderLog = new OrderLog();
            orderLog.setOrderNum(orderNum);
            orderLog.setOperateType("用户确认收货");
            orderLog.setOperateTime(LocalDateTime.now());
            orderLog.setUserId(userId);
            orderLogMapper.insert(orderLog);
            rabbitTemplate.convertAndSend("", "waiting_check_isEvaluate_queue", orderNum, new CorrelationData(UUID.randomUUID().toString()));
        }else {
            throw new RuntimeException("订单状态异常");
        }
    }

    @Override
    public void rollbackOrderStatus(String orderNum) throws Exception {
        // 根据订单号查询订单信息
        ProductOrderInfo orderInfo = this.lambdaQuery()
                .eq(ProductOrderInfo::getOrderNum, orderNum)
                .one();

        if (orderInfo != null) {
            // 假设订单状态字段为 orderStatus，这里将订单状态回滚到未支付状态（根据实际情况修改）
            orderInfo.setOrderState("未支付") ;// 0 表示未支付状态

            // 更新订单信息到数据库
            boolean success = this.updateById(orderInfo);
            if (!success) {
                throw new Exception("订单状态回滚失败，订单号：" + orderNum);
            }
        } else {
            throw new Exception("未找到对应的订单信息，订单号：" + orderNum);
        }
    }

    @Override
    public void send(String orderNum) {
        //判断订单是否存在
        ProductOrderInfo productOrderInfo = productOrderInfoMapper.selectOne(new QueryWrapper<ProductOrderInfo>().eq("order_num", orderNum).eq("order_state", "待发货"));
        if (productOrderInfo==null){
            throw new RuntimeException("订单不存在");
        }
        productOrderInfo.setOrderState("待收货");
        productOrderInfoMapper.updateById(productOrderInfo);
        //记录日志
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNum(orderNum);
        orderLog.setOperateType("平台发货");
        orderLog.setOperateTime(LocalDateTime.now());
        orderLog.setUserId(1);
        orderLogMapper.insert(orderLog);
    }

    @Override
    public List<ProductOrderInfo> getAllOrder() {
        return productOrderInfoMapper.selectList(new QueryWrapper<ProductOrderInfo>().orderByDesc("create_time"));
    }
}
